<template>
  <div class="jcamera">
    <!-- 捕获人脸 -->
    <video
      id="video"
      ref="video"
      :width="width"
      :height="height"
      autoplay
      muted
    >
      您的浏览器不支持 video 标签。
    </video>
    <canvas id="canvas" ref="canvas" :width="width" :height="height" />

    <br />
    <el-select
      v-if="videoDevices.length > 1"
      v-model="deviceId"
      placeholder="请选择摄像头"
      clearable
      @change="
        () => {
          stop()
          tracking()
        }
      "
    >
      <el-option
        v-for="video in videoDevices"
        :key="video.deviceId"
        :label="video.label"
        :value="video.deviceId"
      />
    </el-select>

    <p style="margin-top: 20px">
      {{ trackingText }}
    </p>
  </div>
</template>
<script>
import './tracking.js'
import './face-min.js'

let tracking = window.tracking

export default {
  name: 'JFaceCamera',
  props: {
    width: {
      type: Number,
      default: () => {
        return 640
      },
    },
    height: {
      type: Number,
      default: () => {
        return 480
      },
    },
    frequence: {
      type: Number,
      default: () => {
        return 1
      },
    },
    audio: {
      type: Boolean,
      default: () => {
        return false
      },
    },
  },
  data() {
    return {
      tracker: null,
      trackerTask: null,
      trackingText: null,
      lastCaptureTime: null,
      context: null,
      videoDevices: [],
      deviceId: null,
      suspend: false,
    }
  },
  computed: {
    video() {
      return this.$refs.video
    },
    canvas() {
      return this.$refs.canvas
    },
  },
  mounted() {
    this.$nextTick(() => {
      this.init()
    })
  },
  beforeUnmount() {
    this.stop()
  },
  methods: {
    init() {
      this.context = this.canvas.getContext('2d')

      this.tracker = new tracking.ObjectTracker(['face']) // tracker实例
      this.tracker.setInitialScale(4)
      this.tracker.setStepSize(2)
      this.tracker.setEdgesDensity(0.1)

      this.tracker.on('track', (e) => {
        this.context.clearRect(0, 0, this.canvas.width, this.canvas.height)
        if (e.data.length == 0) {
          return
        }

        e.data.forEach((rect) => {
          this.context.strokeStyle = '#a64ceb'
          this.context.strokeRect(rect.x, rect.y, rect.width, rect.height)
          this.context.font = '11px Helvetica'
          this.context.fillStyle = '#fff'
          this.context.fillText(
            'x: ' + rect.x + 'px',
            rect.x + rect.width + 5,
            rect.y + 11
          )
          this.context.fillText(
            'y: ' + rect.y + 'px',
            rect.x + rect.width + 5,
            rect.y + 22
          )
        })

        let now = new Date().getTime()
        if (
          !this.lastCaptureTime ||
          now > this.lastCaptureTime + this.frequence * 1000
        ) {
          this.capture()
        }
      })
    },
    async tracking() {
      this.videoDevices = []
      let devices = await navigator.mediaDevices.enumerateDevices()
      for (let i in devices) {
        let device = devices[i]
        if (device.kind == 'videoinput') {
          this.videoDevices.push(device)
        }
      }

      if (this.videoDevices.length == 0) {
        this.trackingText = '未找到摄像头'
        return
      } else if (this.videoDevices.length == 1) {
        this.deviceId = this.videoDevices[0].deviceId
      } else if (this.videoDevices.length > 1) {
        if (!this.deviceId) {
          this.trackingText = '请选择摄像头'
          return
        }
      }

      this.trackingText = '正在启动用户谋体...'

      try {
        this.trackerTask = tracking.track('#video', this.tracker, {
          audio: this.audio,
          video: {
            optional: [{ sourceId: this.deviceId }],
          },
        }) // 开始追踪

        this.trackingText = '请调整摄像头至合适位置，将正脸置于框内'
      } catch (e) {
        console.error(e)
        this.trackingText = '访问用户媒体失败'
      }
    },

    stop() {
      if (this.trackerTask) {
        this.trackerTask.stop()
        this.trackerTask = null
      }

      if (this.video && this.video.srcObject) {
        this.video.srcObject.getTracks()[0].stop()
        this.video.srcObject = null
      }

      if (this.context) {
        this.context.clearRect(0, 0, this.canvas.width, this.canvas.height)
      }
    },

    capture() {
      this.lastCaptureTime = new Date().getTime()

      this.context.clearRect(0, 0, this.canvas.width, this.canvas.height)

      this.context.drawImage(this.video, 0, 0, this.width, this.height)

      // 保存为base64格式
      return this.canvas.toDataURL('image/png')
    },
  },
}
</script>
<style lang="scss" scoped>
.jcamera {
  display: flex;
  flex-direction: column;
  align-items: center;

  canvas {
    position: absolute;
  }
}
</style>
